package com.wadesss.flyingformationapp

import android.app.Activity
import android.app.Service
import android.bluetooth.BluetoothDevice
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.annotation.RequiresApi
import io.dronefleet.mavlink.Mavlink2Message
import io.dronefleet.mavlink.MavlinkConnection
import io.dronefleet.mavlink.MavlinkMessage
import io.dronefleet.mavlink.common.Heartbeat
import okhttp3.MediaType
import okhttp3.RequestBody
import org.json.JSONException
import org.json.JSONObject
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.DataInputStream
import java.io.DataOutputStream
import java.lang.reflect.Method
import java.net.InetSocketAddress
import java.net.Socket
import java.nio.ByteBuffer
import java.util.*


class ServerMainReceiver: BroadcastReceiver() {
    private var bind:IBind? = null

    override fun onReceive(context: Context?, intent: Intent?) {
        when(intent?.action)
        {
            "start_bluetooth" -> {
                this.bind?.start_bluetooth(intent)
            }

            "start_socket" -> {
                this.bind?.start_socket(intent)
            }

            "stop_socket" -> {
                this.bind?.stop_socket(intent)
            }

            "stop_bluetooth" -> {
                this.bind?.stop_bluetooth(intent)
            }
        }
    }

    fun setBind(bd: IBind) {
        this.bind = bd
    }

    interface IBind {
        fun start_bluetooth(intent: Intent)
        fun start_socket(intent: Intent)
        fun stop_socket(intent: Intent)
        fun stop_bluetooth(intent: Intent)

    }
}

class SocketService : Service(), ServerMainReceiver.IBind {
    private var localReceiver:ServerMainReceiver = ServerMainReceiver()

    // 消息列表
    private val mMsgList: Array<String> = arrayOf(
            "start_bluetooth",
            "start_socket",
            "stop_socket",
            "stop_bluetooth",
            "start_server",
            "stop_server")

    override fun onCreate() {
        super.onCreate()

        localReceiver = ServerMainReceiver()

        val filter = IntentFilter()
        for(item in mMsgList)
        {
            filter.addAction(item)
        }

        App.instance.localBroadcastManager.registerReceiver(localReceiver, filter)
        localReceiver.setBind(this)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        try {

            if(!App.instance.mSocket.isConnected)
            {
                Thread {
                    try {
                        val pref = getSharedPreferences("Configure", 0)
                        val host = pref.getString("domain", "").toString()
                        val port = pref.getString("port", "").toString().toInt()

                        App.instance.mSocket = Socket()
                        val socSock = InetSocketAddress(host, port)
                        App.instance.mSocket.connect(socSock, 60 * 1000)

                        App.instance.mavlinkConnection = MavlinkConnection.create(
                                App.instance.mSocket.getInputStream(),
                                App.instance.mSocket.getOutputStream())

                        App.instance.mavlinkConnection2 = MavlinkConnection.create(
                                App.instance.bluetoothSocket?.inputStream,
                                App.instance.bluetoothSocket?.outputStream)

                        App.instance.mOutut = DataOutputStream(App.instance.mSocket.getOutputStream())
                        App.instance.mInput = DataInputStream(App.instance.mSocket.getInputStream())

                        App.instance.localBroadcastManager.sendBroadcast(Intent("start_bluetooth"))
                        App.instance.localBroadcastManager.sendBroadcast(Intent("start_socket"))

                        // 获取Token
                        val user = pref.getString("UserName", "").toString()
                        val passwd = pref.getString("Passwd", "").toString()
                        if (user.isNotEmpty()
                            && passwd.isNotEmpty())
                        {
                            val retrofit = Retrofit.Builder()
                                .baseUrl("http://122.9.106.181:915/api/")
                                .addConverterFactory(GsonConverterFactory.create())
                                .build()

                            val root = JSONObject()
                            try {
                                root.put("UserName", user)
                                root.put("pwd", passwd)
                                root.put("sessionid", "null")
                            } catch (e: JSONException) {
                                e.printStackTrace()
                            }

                            val requestBody =
                                RequestBody.create(MediaType.parse("application/json"), root.toString())

                            val api = retrofit.create(APIService::class.java)
                            val call = api.login(requestBody)
                            call!!.enqueue(object : Callback<LoginMessage?> {
                                override fun onResponse(
                                        call: Call<LoginMessage?>?,
                                        response: Response<LoginMessage?>?
                                ) {
                                    if (response != null) {
                                        if (response.code() == 200) {
                                            val data = response.body()
                                            when (data!!.code) {
                                                "0" -> {
                                                    Toast.makeText(
                                                            App.instance.applicationContext,
                                                            "登陆成功",
                                                            Toast.LENGTH_LONG
                                                    ).show()

                                                    val edit = pref.edit()
                                                    edit.putString("token", data.data!!.token)
                                                    edit.apply()
                                                    App.instance.localBroadcastManager.sendBroadcast(Intent("start_server"))
                                                    return
                                                }
                                                else -> {
                                                    Toast.makeText(
                                                            App.instance.applicationContext,
                                                            "登陆失败，" + data.msg,
                                                            Toast.LENGTH_LONG
                                                    ).show()
                                                    App.instance.localBroadcastManager.sendBroadcast(Intent("stop_server"))
                                                    return
                                                }
                                            }
                                        }
                                    }

                                    Toast.makeText(
                                            App.instance.applicationContext,
                                            "登陆失败",
                                            Toast.LENGTH_LONG
                                    ).show()
                                    App.instance.localBroadcastManager.sendBroadcast(Intent("stop_server"))
                                }

                                override fun onFailure(call: Call<LoginMessage?>?, t: Throwable?) {
                                    Toast.makeText(
                                            App.instance.applicationContext,
                                            "无法连接服务器",
                                            Toast.LENGTH_LONG
                                    ).show()
                                    App.instance.localBroadcastManager.sendBroadcast(Intent("stop_server"))
                                }
                            })
                        }
                        else
                        {
                            // 没有录入账号密码，直接进入主界面
                            App.instance.localBroadcastManager.sendBroadcast(Intent("start_server"))
                        }
                    }
                    catch (e: java.net.SocketException)
                    {
                        Handler(Looper.getMainLooper()).post {
                            Toast.makeText(
                                    App.instance.applicationContext,
                                    "无法连接服务器",
                                    Toast.LENGTH_LONG
                            ).show()
                        }

                        App.instance.localBroadcastManager.sendBroadcast(Intent("stop_server"))
                        App.instance.isRun = false
                    }
                    catch (e: java.lang.Exception)
                    {
                        Handler(Looper.getMainLooper()).post {
                            Toast.makeText(
                                    App.instance.applicationContext,
                                    "无法连接服务器",
                                    Toast.LENGTH_LONG
                            ).show()
                        }

                        App.instance.localBroadcastManager.sendBroadcast(Intent("stop_server"))
                        App.instance.isRun = false
                    }
                }.start()
            }
        }
        catch (e: Exception) {
            Handler(Looper.getMainLooper()).post {
                Toast.makeText(
                        App.instance.applicationContext,
                        "无法连接服务器",
                        Toast.LENGTH_LONG
                ).show()
            }

            App.instance.localBroadcastManager.sendBroadcast(Intent("stop_server"))
        }

        return super.onStartCommand(intent, flags, startId)
    }

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    override fun start_bluetooth(intent: Intent) {
        Thread {
            while (App.instance.isRun) {
                try {
                    var message: MavlinkMessage<*>
                    while (App.instance.mavlinkConnection2.next().also { message = it } != null) {

                        // The received message could be either a Mavlink1 message, or a Mavlink2 message.
                        // To check if the message is a Mavlink2 message, we could do the following:
                        if (message is Mavlink2Message<*>) {
                            // This is a Mavlink2 message.
                            val message2 = message as Mavlink2Message<*>
                            if (message2.isSigned) {
                                // This is a signed message. Let's validate its signature.

                            } else {
                                // This is an unsigned message.
                            }
                        } else {
                            // This is a Mavlink1 message.
                        }

                        // When a message is received, its payload type isn't statically available.
                        // We can resolve which kind of message it is by its payload, like so:
                        if (message.payload is Heartbeat) {
                            // This is a heartbeat message
                            val heartbeatMessage = message as MavlinkMessage<*>
                        }

                        Log.d("DeBug:", message.toString())

                        App.instance.mOutut.write(message.rawBytes)
                    }
                } catch (e: java.lang.Exception) {
                    // 断开蓝牙
                    try {
                        App.instance.mClient.disconnect(App.instance.mMac)
                    }
                    catch (err: java.lang.Exception) {

                    }

                    // 3秒后重连
                    Thread.sleep(3000)
                    connect_bluetooth()
                }
            }
        }.start()

        /*
        Thread {
            if (App.instance.bluetoothSocket?.isConnected == true) {

                while(true) {
                    try {
                        val input = App.instance.bluetoothSocket?.inputStream
                        var b = -1
                        while (true) {
                            try {
                                if (App.instance.mOutut != null
                                    && App.instance.mSocket.isConnected) {
                                    b = input!!.read()
                                    if (b != -1)
                                    {
                                        App.instance.mOutut!!.write(b)
                                    }
                                }
                            }
                            catch (e: Exception) {
                                Toast.makeText(
                                        applicationContext,
                                        e.message,
                                        Toast.LENGTH_LONG
                                ).show()
                                Thread.sleep(1000)
                            }

                        }
                    }
                    catch (e: Exception) {
                        Thread.sleep(3000)
                    }
                }

            }
            else
            {
                Toast.makeText(applicationContext, "没有连接蓝牙", Toast.LENGTH_LONG).show()
            }
        }.start()

         */
    }

    override fun start_socket(intent: Intent) {
        Thread {
            while (App.instance.isRun) {
                try {
                    val temp = ByteArray(1024)
                    val len = App.instance.mInput.read(temp)
                    val buff = ByteBuffer.allocate(len)
                    buff.put(temp, 0, len)
                    if (buff.array().isNotEmpty()) {

                        if (App.instance.bluetoothSocket != null
                            && (App.instance.bluetoothSocket?.isConnected == true)
                        ) {
                            App.instance.bluetoothSocket!!.outputStream.write(buff.array())
                        }
                    }
                } catch (e: java.lang.Exception) {
                    Log.d("socket", e.message.toString())
                    // 断开socket
                    try {
                        App.instance.mSocket.close()
                    }
                    catch (err: java.lang.Exception) {

                    }

                    // 3秒后重连
                    Thread.sleep(3000)
                    connect_socket()
                }
            }
        }.start()
    }

    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    fun connect_bluetooth() {
        try {
            val dev = App.instance.bluetoothManager.adapter.getRemoteDevice(App.instance.mMac)

            val m1: Method = BluetoothDevice::class.java.getMethod("createBond")
            m1.invoke(dev)

            val uuid: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
            App.instance.bluetoothSocket =
                dev.createInsecureRfcommSocketToServiceRecord(uuid)

            if (App.instance.bluetoothSocket?.isConnected == true) {
                App.instance.bluetoothSocket!!.close()
            }

            try
            {
                App.instance.bluetoothSocket?.connect()

                App.instance.mavlinkConnection2 = MavlinkConnection.create(
                    App.instance.bluetoothSocket?.inputStream,
                    App.instance.bluetoothSocket?.outputStream)
            }
            catch (e: java.lang.Exception) {
                Handler(Looper.getMainLooper()).post {
                    Toast.makeText(
                            App.instance.applicationContext,
                            "无法连接服务器",
                            Toast.LENGTH_LONG
                    ).show()
                }

                return
            }
        }
        catch (e: java.lang.Exception) {
            Log.d("bluetooth", e.message.toString())
        }

    }

    fun connect_socket() {
        try {
            val pref = getSharedPreferences("Configure", 0)
            val host = pref.getString("domain", "").toString()
            val port = pref.getString("port", "").toString().toInt()

            App.instance.mSocket = Socket()
            val socSock = InetSocketAddress(host, port)
            App.instance.mSocket.connect(socSock, 60 * 1000)
            App.instance.mavlinkConnection = MavlinkConnection.create(
                App.instance.mSocket.getInputStream(),
                App.instance.mSocket.getOutputStream())

            App.instance.mOutut = DataOutputStream(App.instance.mSocket.getOutputStream())
            App.instance.mInput = DataInputStream(App.instance.mSocket.getInputStream())
        }
        catch (e: java.lang.Exception) {
            Log.d("socket", e.message.toString())
        }

    }

    override fun stop_socket(intent: Intent) {

    }

    override fun stop_bluetooth(intent: Intent) {

    }
}